﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;//使用串口
using System.Runtime.InteropServices;//隐藏光标的
using System.Collections.Concurrent;    //使用ConcurrentQueue
using System.Threading;


namespace KMouse
{
	public partial class Form_Main : Form
	{
        public Queue<string> queue_message = new Queue<string>();        

        keyQ kq = new keyQ();
        COM com = new COM();

        public enum eFunc_OP : int    //设定enum的数据类型
        {
            NULL = 0x00,
            EKEY = 0x01,
            CMDLIST = 0x02,
        }

        private eFunc_OP func_op;

        Modbus mdbs = new Modbus();
        Form_Log form_log = new Form_Log();
        FormCmdlist form_cmdlist = new FormCmdlist();

        public Form_Main()
		{
            Dbg.WriteLine("Init compoent start...");

			InitializeComponent();
            
            Dbg.WriteLine("Init compoent done!");
		}

        private void FormMain_Load(object sender, EventArgs e)
		{
            string fullPath = this.GetType().Assembly.Location;
            string exe_name = System.IO.Path.GetFileName(fullPath);//文件名 “Default.aspx”

            int dot_index = exe_name.IndexOf(".");
            exe_name = exe_name.Substring(0, dot_index);

            Param.path_ini_file = ".\\" + exe_name + "Ini.xml";

            this.Text = "KMouse Git" + Param._VersionGit.ToString() + "[" + Param.path_ini_file + "]";

            //恢复参数
            Param.LoadIniParameter();

            //初始化Cmdlist窗体
            form_cmdlist.Init(mdbs, com, this);

            //从参数中回复Main窗体的内容
            textBox_EKey.Text = Param.dict["EKEY_STRING"].ToString();
            func_op = (eFunc_OP)Param.dict["FUNC_OP"];

            Authorize.Get_Init_HW_Info_Done();   //在初始化串口之前，必须获得硬件信息了

            com.ControlModule_Init(comboBox_COMNumber, comboBox_COMBaudrate,
                comboBox_COMCheckBit, comboBox_COMDataBit, comboBox_COMStopBit);
            com.Init(mdbs);

            if((bool)Param.dict["COM_IS_OPEN"] == true)
            {
                bool res = com.Open();
                if(res == true)
                {
                    SetComStatus(res);
                }
            }

            kq.Init(queue_message);

            mdbs.Init(kq, com.serialport, queue_message,
                Delegate_ModbusCallBack_Identify,
                Delegate_ModbusCallBack_Click,
                Delegate_ModbusCallBack_Speed);
            mdbs.echo_en = checkBox_ShowUart.Checked;
            
            Update_Func_OP_State();
            button_Space.Focus();

            form_log.Init(com, mdbs, queue_key_str, queue_message);
                        
            //MessageBox.Show(Authorize.GetUniqueID(), "AU");
             
            Dbg.WriteLine("Init module done:%\n\n", RTC.GetTimeSpan(Program.time_mark_system_init));

            Authorize.Get_Authorize_HW_Info_Start(this);
        }

        private void timer_CloseForm_Tick(object sender, EventArgs e)
        {
            if(com.serialport.IsOpen == true)
            {
                bool res = com.Close();
                if(res == false)
                {
                    return;
                }     
            }

            kq.Close();
            mdbs.Close();

            Func_SaveNewParameter();        //关闭的时候保存参数

			notifyIcon.Dispose();
            this.Close();
            System.Environment.Exit(0);     //把netcom线程也结束了
        }

		private void FormMain_FormClosing(object sender, FormClosingEventArgs e)   //窗体关闭函数
		{
            e.Cancel = true;//取消窗体的关闭
            timer_CloseForm.Enabled = true;
		}
                
        private void Func_SaveNewParameter()
        {
            Param.dict["COM_IS_OPEN"] = button_COMOpen.ForeColor == Color.Green ? true : false;
            Param.dict["COM_SELECT"] = comboBox_COMNumber.SelectedIndex;
            Param.dict["COM_BAUDRATE"] = comboBox_COMBaudrate.SelectedIndex;
            
            Param.dict["EKEY_STRING"] = textBox_EKey.Text;
            Param.dict["FUNC_OP"] = (int)func_op;
            
            form_cmdlist.Update_Cmdlist_Parm();
	              
            //如果参数没有发生变化，就不用去重写ini文件了
            bool result = Param.ChkDictIsEqual(Param.dict, Param.dict_bak);

            if(result == false)
            {
                Dbg.WriteLine("Param ini is changed, save new ini file");
                Param.SaveIniParam();
            }
        }

		private void KMouse_SizeChanged(object sender, EventArgs e)
		{
			if(this.WindowState == FormWindowState.Minimized)  //判断是否最小化
			{
				this.ShowInTaskbar = false; //不显示在系统任务栏
				notifyIcon.Visible = true;  //托盘图标可见
			}
		}

		private void notifyIcon_DoubleClick(object sender, EventArgs e)
		{
			//判断是否已经最小化于托盘 
			//if(WindowState == FormWindowState.Minimized)
			{
				WindowState = FormWindowState.Normal;	//还原窗体显示 
				this.Activate();						//激活窗体并给予它焦点 
				this.ShowInTaskbar = true;				//任务栏区显示图标 
				notifyIcon.Visible = false;				//托盘区图标隐藏 
			}
		}       

        private void button_Func_Click(object sender, EventArgs e)
        {
            if(func_op == eFunc_OP.EKEY)
            {
                func_op = eFunc_OP.CMDLIST;
                button_Run.Enabled = true;
            }
            else if(func_op == eFunc_OP.CMDLIST)
            {
                func_op = eFunc_OP.NULL;
                button_Run.Enabled = false;
            }
            else
            {
                func_op = eFunc_OP.EKEY;
                button_Run.Enabled = true;
            }

            Update_Func_OP_State();
        }

        private void Update_Func_OP_State()
        {
            if(func_op == eFunc_OP.EKEY)
            {
                kq.modbus_kb_waiting_max = keyQ.MODBUS_KB_WAITING_EKEY;
                textBox_EKey.Enabled = true;
                button_Func.Text = "eKey";

                groupBox_Keyboard.Enabled = true;
                groupBox_COM.Enabled = true;
                groupBox_Mouse.Enabled = true;
                checkBox_ShowUart.Enabled = true;
                button_Run.Enabled = true;

                form_cmdlist.Hide();
            }
            else if(func_op == eFunc_OP.CMDLIST)
            {
                kq.modbus_kb_waiting_max = keyQ.MODBUS_KB_WAITING_NORMAL;
                textBox_EKey.Enabled = false;
                button_Func.Text = "CList";

                groupBox_Keyboard.Enabled = false;
                groupBox_COM.Enabled = false;
                groupBox_Mouse.Enabled = false;
                checkBox_ShowUart.Enabled = false;
                button_Run.Enabled = false;
                                
                form_cmdlist.Show();
                form_cmdlist.Location = new System.Drawing.Point(this.Location.X + this.Size.Width, this.Location.Y/* + this.Size.Height*/);
            }
            else
            {
                textBox_EKey.Enabled = false;
                button_Func.Text = "Null";

                groupBox_Keyboard.Enabled = true;
                groupBox_COM.Enabled = true;
                groupBox_Mouse.Enabled = true;
                checkBox_ShowUart.Enabled = true;
                button_Run.Enabled = true;

                form_cmdlist.Hide();
            }
        }
        
        private void timer_background_Tick(object sender, EventArgs e)      //100ms
        {
            this.Invoke((EventHandler)(delegate
            {
                label_SuccessCmdCnt.Text = "Success: " + mdbs.success_cnt.ToString();
                label_FailCmdCnt.Text = "Fail: " + mdbs.fail_cnt.ToString();
            }));
        }

        void Delegate_ModbusCallBack_Identify(uint value)
        {
            this.Invoke((EventHandler)(delegate
            {                
                button_P_Identify.Text = "ID(" + value.ToString() + ")";
            }));
        }

        void Delegate_ModbusCallBack_Click(uint value)
        {
            this.Invoke((EventHandler)(delegate
            {
                if(button_ClickLeft.Enabled == false)
                {
                    button_ClickLeft.Enabled = true;
                }
                if(button_ClickRight.Enabled == false)
                {
                    button_ClickRight.Enabled = true;
                }
            }));
        }

        void Delegate_ModbusCallBack_Speed(uint value)
        {
            this.Invoke((EventHandler)(delegate
            {
        	    if(button_SpeedUp.Enabled == false)
			    {
				    button_SpeedUp.Enabled = true;
			    }
			    if(button_SpeedDown.Enabled == false)
			    {
				    button_SpeedDown.Enabled = true;
			    }
			    if(kq.mouse_speed_chk == false)
			    {
				    kq.mouse_speed_chk = true;
			    }
			    label_MouseSpeed.Text = value.ToString();
            }));
        }

        private void checkBox_ShowUart_CheckedChanged(object sender, EventArgs e)
        {
            mdbs.echo_en = checkBox_ShowUart.Checked;

            if(checkBox_ShowUart.Checked == true)
            {   
                form_log.Show();
                form_log.Location = new System.Drawing.Point(this.Location.X + this.Size.Width, this.Location.Y/* + this.Size.Height*/);
            }
            else
            {
                form_log.Hide();
            }
        }


        /********************与串口控制相关的 Start***************************/

        private void comboBox_COMNumber_DropDown(object sender, EventArgs e)
        {
            com.comboBox_COMNumber_DropDown(sender);
        }

        private void comboBox_COMNumber_SelectedIndexChanged(object sender, EventArgs e)
        {
            com.comboBox_COMNumber_SelectedIndexChanged(sender);
        }

        private void comboBox_COMBaudrate_SelectedIndexChanged(object sender, EventArgs e)
        {
            com.comboBox_COMBaudrate_SelectedIndexChanged(sender);
        }

        private void comboBox_COMDataBit_SelectedIndexChanged(object sender, EventArgs e)
        {
            com.comboBox_COMDataBit_SelectedIndexChanged(sender);
        }

        private void comboBox_COMCheckBit_SelectedIndexChanged(object sender, EventArgs e)
        {
            com.comboBox_COMCheckBit_SelectedIndexChanged(sender);
        }

        private void comboBox_COMStopBit_SelectedIndexChanged(object sender, EventArgs e)
        {
            com.comboBox_COMStopBit_SelectedIndexChanged(sender);
        }

        public void SetComStatus(bool IsRunning)
        {
            if(IsRunning == true)
            {
                button_COMOpen.Text = "COM is opened";
                button_COMOpen.ForeColor = Color.Green;
                comboBox_COMCheckBit.Enabled = false;
                comboBox_COMDataBit.Enabled = false;
                comboBox_COMNumber.Enabled = false;
                comboBox_COMStopBit.Enabled = false;
            }
            else
            {
                button_COMOpen.Text = "COM is closed";
                button_COMOpen.ForeColor = Color.Red;
                comboBox_COMCheckBit.Enabled = true;
                comboBox_COMDataBit.Enabled = true;
                comboBox_COMNumber.Enabled = true;
                comboBox_COMStopBit.Enabled = true;

                if(button_COMOpen.Enabled == false)
                {
                    button_COMOpen.Enabled = true;
                }
            }
        }

        private void button_ComOpen_Click(object sender, EventArgs e)
        {
            com.button_ComOpen_Click(sender, this);
        }

        private void comboBox_COMNumber_DropDownClosed(object sender, EventArgs e)
        {
            com.comboBox_COMNumber_DropDownClosed(sender);
        }


        class User
        {
            public string ID
            {
                get; set;
            }
            public string Name
            {
                get; set;
            }
            public string Age
            {
                get; set;
            }
            public string Explain
            {
                get; set;
            }
        }
        private void button_Param_Click(object sender, EventArgs e)
        {
            Func_SaveNewParameter();
        }
        /********************与串口控制相关的 End***************************/
    }
}
